package com.yangrr.weblog.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yangrr.weblog.common.domain.dos.UserDO;
import com.yangrr.weblog.common.domain.dos.UserRoleDO;
import com.yangrr.weblog.common.domain.mapper.UserMapper;
import com.yangrr.weblog.common.domain.mapper.UserRoleMapper;
import com.yangrr.weblog.common.enums.ResponseCodeEnum;
import com.yangrr.weblog.common.exception.BizException;
import com.yangrr.weblog.common.utils.Response;
import com.yangrr.weblog.web.model.vo.comment.FindQQUserInfoReqVO;
import com.yangrr.weblog.web.model.vo.comment.FindQQUserInfoRspVO;
import com.yangrr.weblog.web.model.vo.user.RegisterDto;
import com.yangrr.weblog.web.service.UserService;
import com.yangrr.weblog.web.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @PATH impl.service.com.yangrr.weblog.web.UserServiceImpl
 * @Author YangRR
 * @CreateData 2025-05-08 13:48
 * @Description:
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${api-key}")
    private String apiKey;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional
    public Response register(RegisterDto registerDto) {
        String username = registerDto.getUsername();
        String password = registerDto.getPassword();
        String confirmPassword = registerDto.getConfirmPassword();
        String email = registerDto.getEmail();
        String code = registerDto.getCode();

        if (!password.equals(confirmPassword)) {
            return Response.fail(ResponseCodeEnum.REGISTER_PASSWORD_NOT_SAME);
        }

        // 校验用户名和邮箱是否存在
        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username).
                or().eq("email", email);
        UserDO user = userMapper.selectOne(queryWrapper);
        if (user != null) {
            return Response.fail(ResponseCodeEnum.REGISTER_EXIST);
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encode = encoder.encode(password);

        //验证验证码
        if (!code.equals(redisTemplate.opsForValue().get(email))) {
            return Response.fail(ResponseCodeEnum.REGISTER_CODE_ERROR);
        }

        //判断是否是qq邮箱
        if (email.contains("@qq.com")) {
            // 如果是，尝试获取QQ信息
            String qqNumber = email.split("@")[0];
            FindQQUserInfoRspVO findQQUserInfoRspVO = null;
            try{
                //如果是，获取信息
                findQQUserInfoRspVO = findQQUserInfo(FindQQUserInfoReqVO.builder().qq(qqNumber).build());
            }catch (Exception e){
                log.warn("获取QQ用户信息失败，QQ号: {}, 原因: {}", qqNumber, e.getMessage());
                randomUser(username, encode, email);

                //赋予新用户role
                UserRoleDO roleVisitor = UserRoleDO.
                        builder().
                        username(username).
                        role("ROLE_VISITOR").
                        build();

                userRoleMapper.insert(roleVisitor);

                return Response.success();
            }
           if (findQQUserInfoRspVO != null) {
                //如果或取到了，插入数据库
                String avatar = findQQUserInfoRspVO.getAvatar();
                String nickname = findQQUserInfoRspVO.getNickname();
                UserDO newUser = UserDO.builder().
                        username(username).
                        password(encode).
                        email(email).
                        avatar(avatar).
                        showName(nickname).
                        build();
                userMapper.insert(newUser);
            }else {
                //如果获取不到，随机生成昵称后插入数据库
               randomUser(username, encode, email);
           }
        } else {
            //如果不是，随机生成昵称后插入数据库
            randomUser(username, encode, email);
        }

        //赋予新用户role
        UserRoleDO roleVisitor = UserRoleDO.
                builder().
                username(username).
                role("ROLE_VISITOR").
                build();

        userRoleMapper.insert(roleVisitor);

        return Response.success();
    }

    private void randomUser(String username, String encode, String email) {
        // 格式: yangrr + 6位随机数 = 12字符
        int random = ThreadLocalRandom.current().nextInt(100000, 1000000);
        String showName = "yangrr" + random;
        UserDO newUser = UserDO.builder().
                username(username).
                password(encode).
                email(email).
                showName(showName).
                build();
        userMapper.insert(newUser);
    }

    @Override
    public FindQQUserInfoRspVO findQQUserInfo(FindQQUserInfoReqVO findQQUserInfoReqVO) {
        String qq = findQQUserInfoReqVO.getQq();

        // 校验 QQ 号
        if (!StringUtil.isPureNumber(qq)) {
            log.warn("昵称输入的格式不是 QQ 号: {}", qq);
            throw new BizException(ResponseCodeEnum.NOT_QQ_NUMBER);
        }

        // 请求第三方接口
        String url = String.format("https://api.nsmao.net/api/qq/query?qq=%s&key=%s", qq, apiKey);
        String result = restTemplate.getForObject(url, String.class);

        log.info("通过 QQ 号获取用户信息: {}", result);

        // 解析响参
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String, Object> map = objectMapper.readValue(result, Map.class);
            if (Objects.equals(map.get("code"), HttpStatus.OK.value())) {

                // 获取响应参数中 data 节点下的数据
                Map<String, Object> data = (Map<String, Object>) map.get("data");

                if (!CollectionUtils.isEmpty(data)) {
                    // 获取用户头像、昵称、邮箱
                    return FindQQUserInfoRspVO.builder()
                            .avatar(String.valueOf(data.get("avatar")))
                            .nickname(String.valueOf(data.get("nick")))
                            .mail(String.valueOf(data.get("email")))
                            .build();
                }
            }

            return null;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
